Skip to content

Surface legroom + amenities + seatmap from gflight responses (work-5ewe)#11

Merged
ak2k merged 2 commits into
mainfrom
worktree-work-5ewe-legroom
May 15, 2026
Merged

Surface legroom + amenities + seatmap from gflight responses (work-5ewe)#11
ak2k merged 2 commits into
mainfrom
worktree-work-5ewe-legroom

Conversation

@ak2k

@ak2k ak2k commented May 15, 2026

Copy link
Copy Markdown
Owner

Summary

  • New legroom column on flight search output: pitch in inches (red for BELOW, green for ABOVE), cabin letter (Y/W/J/F), premium-cabin seat-type labels (Lie Flat / Suite / etc.), and single-glyph amenity icons.
  • Wifi rendered as 📶 (free) or 📶$ in yellow (paid); 1-col Unicode for power ( plug / USB) and video ( live TV / seatback on-demand / BYOD streaming).
  • New flight seatmap subcommand resolves a flight to its seatmaps.com URL via one HTTP call to travelarrow.io's /api/s (or --no-fetch to just emit the API URL).
  • Dim glyph-legend footer prints below the table whenever legroom data renders.

Why the path got non-obvious

The bd item assumed we'd need to capture a third-party API (api.travelarrow.io/v3/deals). The actual finding: the data is in-band in Google Flights' own /GetShoppingResults response at per-leg tuple indices 12-17 — the Legrooms+ extension's load_flight_data.js parses exactly those positions. We just had to read them.

The Legrooms+ extension v11.5.0's bit positions have drifted since the extension was last updated, so a direct port read every wifi flag as False. I empirically recalibrated the mapping 2026-05 by driving Google Flights via Patchright, expanding flight detail panels, scraping the rendered amenity labels, and correlating against the bit array. The headline fix: wifi moved from a single Boolean at [0] to a three-state enum at [11] (1=none / 2=free / 3=paid). Both ground-truth flights (AA 952 with "Free Wi-Fi + Stream-to-device" and B6 1072 with "Free Wi-Fi + Live TV") now decode every field — pitch, legroom class, cabin, aircraft, power, video, wifi — to a value that exactly matches Google's UI.

Detailed index map, enum decodings, ground-truth validation set, and the calibration story are in docs/memories/legroom_recipe.md.

Test plan

  • uv run pytest tests/ — 161 passing (24 new tests across test_legroom_parser.py and test_seatmap.py)
  • basedpyright src/flight_cli/ — 0 errors / 0 warnings
  • Live smoke: flight search MIA LGA --dep 2026-06-16 matches Google's labels for AA 952 (Y 30" 📶↯◰) and B6 1072 (Y 32" 📶↯▶)
  • Live smoke: flight search JFK DXB --dep 2026-09-10 surfaces paid wifi correctly (📶$↯▷ on RJ regional, 📶↯▷ on QR mainline)
  • Live smoke: flight search MCO LAS --dep 2026-09-10 shows F9 with no glyphs (no wifi/IFE/power) and WN with 📶⌁◰ (BYOD streaming + USB-only + free wifi)
  • flight seatmap JFK LHR DL2 --date 2026-08-15 --aircraft "Airbus A330" returns a working seatmaps.com URL

ak2k added 2 commits May 15, 2026 19:31
The Legrooms+ Chrome extension overlays cabin, pitch, and amenity info on
Google Flights search results. Originally I assumed we'd need to capture a
third-party API (api.travelarrow.io) to mirror that — but the extension's
load_flight_data.js shows the data is already in-band in Google's own
/GetShoppingResults response at per-leg tuple indices 12-17. Our gflight
backend already hits that endpoint via fli; we just had to read the fields.

The Legrooms+ extension v11.5.0's bit positions have drifted since the
extension was last updated. I empirically recalibrated 2026-05 by driving
Google Flights via Patchright, scraping the rendered amenity labels from
the detail panel, and correlating against the bit array. The wifi signal
in particular moved from a single Boolean at [0] to a three-state enum at
[11] (1=none, 2=free, 3=paid). Validated end-to-end against AA 952 and
B6 1072: every decoded field (pitch, legroom class, cabin, aircraft,
power, video, wifi) exactly matches Google's UI labels.

Seatmap URLs are a separate per-flight concern. `flight seatmap` is a new
subcommand that hits travelarrow.io/api/s (the same endpoint the Legrooms+
extension uses on click) and resolves to a seatmaps.com URL.

Field detail and the calibration story are in docs/memories/legroom_recipe.md.
@ak2k ak2k merged commit ce8482f into main May 15, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant